def table_attributes(self,attributes):
    output = []
    output.append(self.common_attributes(attributes))
    output.append(self.render_attribute('summary',    attributes))
    output.append(self.render_attribute('width',      attributes))
    output.append(self.render_attribute('border',     attributes))
    output.append(self.render_attribute('cellspacing',attributes))
    output.append(self.render_attribute('cellpadding',attributes))
    return u''.join(output)

def table_common_attributes(self,attributes):
    output = []
    output.append(self.common_attributes(attributes))
    output.append(self.render_attribute('align',  attributes))
    output.append(self.render_attribute('char',   attributes))
    output.append(self.render_attribute('charoff',attributes))
    output.append(self.render_attribute('valign', attributes))
    return u''.join(output)

def table_cell_attributes(self,attributes):
    output = []
    output.append(self.table_common_attributes(attributes))
    output.append(self.render_attribute('rowspan', attributes))
    output.append(self.render_attribute('colspan', attributes))
    output.append(self.render_attribute('headers', attributes))
    output.append(self.render_attribute('abbr',    attributes))
    output.append(self.render_attribute('scope',   attributes))
    output.append(self.render_attribute('axis',    attributes))
    return u''.join(output)

table_body_attributes   = table_common_attributes
table_footer_attributes = table_common_attributes
table_header_attributes = table_common_attributes
table_row_attributes    = table_common_attributes

def render_table_cell(self,content=None,attributes={},cell_type=None,render_content=None):
    if not cell_type:
        cell_type = 'td'
    assert cell_type in ('td','th')
    if render_content:
        content = render_content(content)
    if content:
        colspan = 1
        if 'colspan' in attributes:
            colspan = int(attributes['colspan'])
        return colspan,self.render_tag(cell_type,self.escape(content),attributes,
                                       render_attributes=self.table_cell_attributes)
    return 0,u''

def render_table_row(self,row=[],attributes={},cell_type=None,render_content=None):
    output  = []
    columns = 0
    for cell in row:
        if isinstance(cell,dict):
            colspan,content = self.render_table_cell(cell.get('content',u''),cell_type=cell_type,
                                                     attributes=cell.get('attributes',{}),
                                                     render_content=render_content)
        else:
            colspan,content = self.render_table_cell(cell,cell_type=cell_type,
                                                     render_content=render_content)
        output.append(content)
        columns = columns + colspan
    return columns,self.render_tag('tr',self.safe(u''.join(output)),attributes,
                                   render_attributes=self.table_row_attributes)

def render_table_rows(self,rows=[],cell_type=None,colcount=0,render_content=None):
    output   = []
    rowcount = 0
    for row in rows:
        if isinstance(row,dict):
            columns,content = self.render_table_row(row.get('content',()),cell_type='td',
                                                    attributes=row.get('attributes',{}),
                                                    render_content=render_content)
        else:
            columns,content = self.render_table_row(row,cell_type='td',
                                                    render_content=render_content)
        if colcount != columns:
            raise ValueError,"{0} columns required and {1} given".format(colcount,columns)
        if content:
            output.append(content)
            rowcount = rowcount + 1
    return rowcount,self.safe(u''.join(output))

def render_table_footer(self,footer=[],attributes={},colcount=0,render_content=None):
    rowcount,content = self.render_table_rows(footer,cell_type='td',colcount=colcount,
                                              render_content=render_content)
    return rowcount,self.render_tag('tfoot',content,attributes,
                                    render_attributes=self.table_footer_attributes)

def format_table_header(self,request=None,content=None,attributes={},field=None):
    if request:
        if 'sort' in request.GET and request.GET['sort'] == field:
            return self.format_table_header_active(request,content,attributes,field)
        else:
            return self.format_table_header_passive(request,content,attributes,field)
    return self.format_table_header_simple(content,attributes)

def format_table_header_active(self,request,content,attributes,field):
    link_order = 'asc'
    output     = []
    sort_order = request.GET.get('order','asc')
    if sort_order == 'asc':
        classnames = u'ui-icon ui-icon-arrowthick-1-n'
        link_order = 'desc'
    else:
        classnames = u'ui-icon ui-icon-arrowthick-1-s'
        link_order = 'asc'
    query = dict(request.GET)
    query.update({'sort':field,'order':link_order})
    output.append(self.render_tag('span',sort_order,attributes={
                                  'class':classnames,
                                  'style':u'display: inline-block;'}))
    output.append(self.render_link(content,url=request.path,query=query,
                                   attributes={'title':'sort by {0}'.format(content)}))
    return {'content':self.safe(u''.join(output)),'attributes':attributes}

def format_table_header_passive(self,request,content,attributes,field):
    query = dict(request.GET)
    query.update({'sort':field,'order':'asc'})
    return {'content':self.render_link(content,url=request.path,query=query,
                                       attributes={'title':'sort by {0}'.format(content)}),
            'attributes':attributes}

def format_table_header_simple(self,content,attributes):
    return {'content':content,'attributes':attributes}

def render_table_header(self,header=[],attributes={},request=None,render_content=None):
    output = []
    for column in header:
        if not isinstance(column,dict):
            output.append(self.format_table_header(content=column))
        else:
            output.append(self.format_table_header(request,**column))
    columns,content = self.render_table_row(output,cell_type='th',render_content=render_content)
    return columns,self.render_tag('thead',content,attributes,
                                   render_attributes=self.table_header_attributes)

def render_table_bodies(self,bodies=[],colcount=0,render_content=None):
    output   = []
    rowcount = 0
    for body in bodies:
        if isinstance(body,dict):
            rows,content = self.render_table_body(body.get('content',()),colcount=colcount,
                                                  attributes=body.get('attributes',{}),
                                                  render_content=render_content)
        else:
            rows,content = self.render_table_body(body,colcount=colcount,
                                                  render_content=render_content)
        if content:
            output.append(content)
            rowcount = rowcount + rows
    return rowcount,self.safe(u''.join(output))

def render_table_body(self,body=[],attributes={},colcount=0,render_content=None):
    rowcount,content = self.render_table_rows(body,cell_type='td',colcount=colcount,
                                              render_content=render_content)
    return rowcount,self.render_tag('tbody',content,attributes,
                                    render_attributes=self.table_body_attributes)

def render_table(self,bodies=[],caption='',header=[],footer=[],attributes={},empty='',request=None,
                 render_content=None):
    output = []
    colcount,header_content = self.render_table_header(header,request=request,
                                                       render_content=render_content)
    rowcount,footer_content = self.render_table_footer(footer,colcount=colcount,
                                                       render_content=render_content)
    rowcount,bodies_content = self.render_table_bodies(bodies,colcount=colcount,
                                                       render_content=render_content)
    output.append(self.render_tag('caption',caption))
    output.append(header_content)
    output.append(footer_content)
    if rowcount:
        output.append(bodies_content)
    elif empty:
        output.append(self.render_tag('tbody',
                      self.render_tag('tr',
                      self.render_tag('td',empty,attributes={'colspan':colcount}))))
    else:
        output = []
    return self.render_tag('table',self.safe(u''.join(output)),attributes,
                           render_attributes=self.table_attributes)

